﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
/*
 * 运算符重载 vs 函数重载核心区别：
 * 1. 函数重载：同名函数通过参数列表区分（自由定义）
 * 2. 运算符重载：为已有运算符赋予类类型的新语义（严格受限）
 */

//运算符重载的关键字：operator，书写形式就是 "返回类型 operator需要重载的运算符(参数列表)"

 // === 运算符重载核心规则 ===
 // 规则1：参数数量必须匹配运算符的"元"
 //   - 类内定义：二元运算符显式1个参数（+this），一元运算符显式0个参数
 //   - 全局定义：参数数量严格匹配运算符元数
 // 示例：
//    class Vector {
//    public:
//        Vector operator+(const Vector& rhs); // 类内二元：显式1参数（this+rhs）
//        Vector operator-() const;            // 类内一元：显式0参数（this）
//};

// 规则2：至少一个操作数为类类型（防止修改基本类型行为）
//   - 错误示例：int operator+(int a, int b); 
//   - 合法示例：Time operator+(Time t, int s);

// 规则3：禁止重载的运算符（语法禁区）
//   .* :: sizeof ?: .  typeid static_cast dynamic_cast等
//   - 特别注意：逗号运算符（,）可以重载，但极易引发歧义

// 规则4：优先级和结合性不可更改
//   - 重载的&&仍保持短路特性，重载的+仍左结合

// === 特殊场景补充 ===
// 1. 流运算符必须全局重载（<< / >>）
// 2. 下标运算符[]必须返回引用（支持修改）
// 3. 函数调用运算符()实现仿函数


//运算符重载定义在全局使用示例：
//
//class Data//由于运算符重载函数必须要操作类，因此先创建一个类
//{
//public:
//	Data(int year = 2025, int month = 0, int day = 0)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
// //由于在全局写了运算符重载函数，所以只能妥协将成员变量放在公有处
//	int _year = 0;
//	int _month = 0;
//	int _day = 0;
//};
//
//int operator-(Data a, Data b)//此运算符重载的含义是计算Data类中日期的差值
//{
//	return b._year * 365 + b._month * 30 + b._day - 
//		(a._year * 365 + a._month * 30 + a._day);//此处为方便实验，按一年365天，一月30天进行计算
//}
//
//int main()
//{
//	Data a(2025, 7, 8);
//	Data b(2025, 7, 30);
//	std::cout << operator-(a, b) << std::endl;
//	return 0;
//}


//运算符重载定义在类中使用示例：

class Data//由于运算符重载函数必须要操作类，因此先创建一个类
{
public:
	Data(int year = 2025, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//在类中运算符重载函数：
	//这里歪打正着发现了类中访问私有成员的隐藏规则：//类中访问私有成员的隐藏规则：“​​同类对象之间可以通过类内成员函数互相访问私有成员​​”
	//原本我是以为b._year * 365 + b._month * 30 + b._day应该会导致报错的，结果正常运行了
	//查询发现私有成员居然可以在相同类不同变量（即同类所有实例）中相互访问
	int operator-(Data b)//此运算符重载的含义是计算Data类中日期的差值
	{
		return b._year * 365 + b._month * 30 + b._day -
			(_year * 365 + _month * 30 + _day);//此处为方便实验，按一年365天，一月30天进行计算
	}
private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};

int main()
{
	Data a(2025, 7, 8);
	Data b(2025, 7, 30);
	std::cout << a.operator-(b) << std::endl;
	//a.operator-(b)其实就相当于全局运算符重载的operator-(a, b)，只不过类内通过this指针传递了a其中的信息
	return 0;
}
//引子：可以看到，int operator-(Data b)中b的类型设置为了Data，但实际上，该函数并不需要对b中信息进行修改
//也就是说，应该将b的类型设置为const Data，那对此，a又该怎么避免被更改的风险呢？这就和接下来要学的拷贝构造息息相关了
//事实上，使用拷贝构造的话，最好将函数中b的类型改为const Data& b……

//以下是自己的理解与总结
//“重载”这个词已经在函数重载中见过了，运算符重载的含义和函数重载类似，就是使一个运算符具备多种功能
//但运算符重载的限制条件（语法规则）却和函数重载有着显著差别
//1.x元运算符，其运算符重载的参数就要有x个
//（若该运算符重载位于类中，则显式看到的运算符为x-1个，但实际仍为两个，隐藏了this指针参数）
//2.运算符重载的参数或返回值中必须有类的类型，即只有对类才能够使用运算符重载
//3.能够进行运算符重载的运算符是C++规定好的，并不能自己创建，其中最需要注意的是
//.*  ::  sizeof  ?:  .五个运算符最容易出错，它们是不可以重载的
//4.运算符重载后，其运算优先级和结合方式与原运算符一致

